package com.zxq.ruoyi.asyn;

import com.zxq.ruoyi.domain.IotProduct;
import com.zxq.ruoyi.domain.IotProductFrame;
import com.zxq.ruoyi.enums.EProductState;
import com.zxq.ruoyi.enums.EProtocol;
import com.zxq.frame.core.EFrame;
import com.zxq.ruoyi.network.tcp.TcpNetty;
import com.zxq.ruoyi.network.tcp.cache.TcpChannelCache;
import com.zxq.ruoyi.network.tcp.handler.TCPDispatchHandlerFactory;
import com.zxq.ruoyi.network.tcp.handler.TCPDispatchHandlerGatherProxy;
import com.zxq.ruoyi.network.tcp.handler.dispatch.TCPDispatchHandler;
import com.zxq.ruoyi.service.impl.IotProductFrameServiceImpl;
import com.zxq.ruoyi.service.impl.IotProductServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

@Service
@Slf4j
public class AsynProductService {

    /**
     * netty保存产品id，和task任务的接口
     */
    ConcurrentHashMap<Long, TcpNetty> nettyTask = new ConcurrentHashMap<>();
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(8);

    /**
     * 产品服务
     */
    @Autowired
    IotProductServiceImpl iotProductService;

    /**
     * 产品协议服务
     */
    @Autowired
    IotProductFrameServiceImpl iotProductFrameService;

    /**
     * 运行
     */
    public void changeState(Long productId) {
        IotProduct iotProduct = iotProductService.selectIotProductById(productId);
        Integer protocol =  iotProduct.getProtocolType().intValue();
        EProtocol eProtocol = EProtocol.getType(protocol);

        if (eProtocol == EProtocol.TCP) {
            EProductState productState = EProductState.getType(iotProduct.getState().intValue());
            switch (productState){
                case prepare:{
                    run(iotProduct);
                }
                break;
                case run: {
                    TcpNetty tcpNetty =  nettyTask.get(productId);
                    if(tcpNetty != null) {
                        tcpNetty.cancel();
                        iotProduct.setState(EProductState.stop.getValue().longValue());
                        iotProductService.updateIotProduct(iotProduct);
                        log.info(String.format("stop product %s  port:%s",iotProduct.getName(),iotProduct.getTransferPort()));
                    }
                }
                break;
                case stop:{
                    iotProduct.setState(EProductState.prepare.getValue().longValue());
                    iotProductService.updateIotProduct(iotProduct);
                    nettyTask.remove(productId);
                    log.info(String.format("prepare product %s  port:%s",iotProduct.getName(),iotProduct.getTransferPort()));
                }
                break;

            }
        }
    }

    /**
     * 运行iot服务
     * @param iotProduct
     */
    public void run(IotProduct iotProduct){

      //需要添加分发逻辑
        IotProductFrame iotProductFrameDo = new  IotProductFrame();
        iotProductFrameDo.setProductId(iotProduct.getId());
        List<IotProductFrame> iotProductFrameDoList = iotProductFrameService.selectIotProductFrameList(iotProductFrameDo);

        TCPDispatchHandlerGatherProxy tcpDispatchHandlerGatherProxy = new TCPDispatchHandlerGatherProxy();
        iotProductFrameDoList.forEach(item -> {
            Integer frameType = item.getFrameId().intValue();
            EFrame eFrame = EFrame.getType(frameType.intValue());
            TCPDispatchHandler tcpDispatchHandler = TCPDispatchHandlerFactory.create(eFrame);
            log.info("handler:" + tcpDispatchHandler.getClass().getSimpleName());
            tcpDispatchHandlerGatherProxy.addHandler(tcpDispatchHandler);
        });
        TcpNetty tcpNetty = new TcpNetty(iotProduct.getTransferPort().intValue(),tcpDispatchHandlerGatherProxy);
        nettyTask.put(iotProduct.getId(), tcpNetty);
        executorService.execute(tcpNetty);
        log.info(String.format("run product %s  port:%s",iotProduct.getName(),iotProduct.getTransferPort()));
        iotProduct.setState(EProductState.run.getValue().longValue());
        iotProductService.updateIotProduct(iotProduct);
    }



    /**
     * 结束
     */
    public void delete(Long[] productIds) {
        for(Long productId:productIds) {
            TcpNetty tcpNetty = nettyTask.get(productId);
            if (tcpNetty != null) {
                tcpNetty.cancel();
                nettyTask.remove(productId);
            }
        }
    }




    @PostConstruct
    public void initStart(){
        IotProduct iotProduct = new IotProduct();
        iotProduct.setState(EProductState.run.getValue().longValue());
        List<IotProduct> iotProducts =iotProductService.selectIotProductList(iotProduct);
        for (IotProduct item: iotProducts){
                run(item);
        }
    }





}
